package file

import (
	"archive/zip"
	"io"
	"os"
	"path"
	"path/filepath"

	. "gitee.com/tomatomeatman/golang-repository/bricks/model"
	Log "github.com/cihub/seelog"
)

type ZipUtil struct {
}

/**
 * 打包成zip文件
 * src 源文件夹
 * target 目标文件名
 */
func (this ZipUtil) Create(source string, target string) *MsgEmity {
	os.MkdirAll(path.Dir(target), os.ModePerm) //创建多级目录

	targetFile, err := os.Create(target) // 创建目标 zip 文件
	if err != nil {
		Log.Error("创建目标zip文件失败:", err)
		return MsgEmity{}.Err(1001, "创建目标zip文件失败")
	}

	defer targetFile.Close()

	// 创建 zip.Writer
	zipWriter := zip.NewWriter(targetFile)
	defer zipWriter.Close()

	// 获取需要打包的所有文件
	filepath.Walk(source, func(path string, info os.FileInfo, err error) error {
		if err != nil {
			Log.Error("打包zip文件失败:", err)
			//return MsgEmity{}.Err(1002, "打包zip文件失败")
			return err
		}

		// 创建新的 zip 文件头信息
		header, err := zip.FileInfoHeader(info)
		if err != nil {
			Log.Error("创建新的zip文件头信息失败:", err)
			// return MsgEmity{}.Err(1003, "创建新的zip文件头信息失败")
			return err
		}
		// 设置文件头信息中的 Name 字段
		header.Name, err = filepath.Rel(source, path)
		if err != nil {
			return err
		}

		// 判断当前路径是否为一个文件夹
		if info.IsDir() {
			// 如果是文件夹，创建文件夹信息
			header.Name += "/"
			header.Method = zip.Store
		} else {
			// 如果是文件，打开文件准备读取内容
			header.Method = zip.Deflate
		}

		// 将新的文件头信息写入到 zip.Writer 中
		writer, err := zipWriter.CreateHeader(header)
		if err != nil {
			Log.Error("新的文件头信息写入失败:", err)
			// return MsgEmity{}.Err(1004, "新的文件头信息写入失败")
			return err
		}

		// 如果当前路径是一个文件，读取文件内容并写入 zip.Writer 中
		if !info.IsDir() {
			file, err := os.Open(path)
			if err != nil {
				Log.Error("指定文件不存在:", err)
				// return MsgEmity{}.Err(1005, "指定文件不存在")
				return err
			}
			defer file.Close()

			_, err = io.Copy(writer, file)
			if err != nil {
				Log.Error("复制文件失败:", err)
				// return MsgEmity{}.Err(1006, "复制文件失败")
				return err
			}
		}

		return nil
	})

	return MsgEmity{}.Success(1999, "打包结束")
}
